// -----------------------------------------------------------------------------
// Copyright (c) 2014-2023 All rights reserved
// *********************************************************************************
// Project Name : BarrelShifter
// Author       : DFY
// File Name    : bsh_32.v
// Abstract     : 32bit Barrel Shift Registers


module bsh_32 (
	input		[31:0]	data_in,//	输入数据
	input 		 		dir,   //	0：循环左移 | 1：循环右移
	input 		[ 4:0]	sh,	//位移值，取值0~31

	output 		[31:0]	data_out//输出数据
);

//=================================================================================
// Signal and Parameter declaration
//=================================================================================
reg [31:0]	shift_out1;
reg [31:0]	shift_out2;
reg [31:0]	shift_out3;
reg [31:0]	shift_out4;
reg [31:0]	shift_out5;
//=================================================================================
// Body
//=================================================================================

// level 1
always @(*) begin 
	case({dir,sh[0]})
		2'b01		:	shift_out1 = {data_in[30:0],data_in[31]};
		2'b11		:	shift_out1 = {data_in[0],data_in[31:1]};
		2'b00,2'b10 : 	shift_out1 = data_in;
		default 	: 	shift_out1 = data_in;
	endcase
end

// level 2
always @(*) begin 
	case({dir,sh[1]})
		2'b01		:	shift_out2 = {shift_out1[29:0],shift_out1[31:30]};
		2'b11		:	shift_out2 = {shift_out1[ 1:0],shift_out1[31:2]};
		2'b00,2'b10 : 	shift_out2 = shift_out1;
		default 	: 	shift_out2 = shift_out1;
	endcase
end

// level 3
always @(*) begin 
	case({dir,sh[2]})
		2'b01		:	shift_out3 = {shift_out2[27:0],shift_out2[31:28]};
		2'b11		:	shift_out3 = {shift_out2[ 3:0],shift_out2[31:4]};
		2'b00,2'b10 : 	shift_out3 = shift_out2;
		default 	: 	shift_out3 = shift_out2;
	endcase
end

// level 4
always @(*) begin 
	case({dir,sh[3]})
		2'b01		:	shift_out4 = {shift_out3[23:0],shift_out3[31:24]};
		2'b11		:	shift_out4 = {shift_out3[ 7:0],shift_out3[31:8]};
		2'b00,2'b10 : 	shift_out4 = shift_out3;
		default 	: 	shift_out4 = shift_out3;
	endcase
end

// level 5
always @(*) begin 
	case({dir,sh[4]})
		2'b01		:	shift_out5 = {shift_out4[15:0],shift_out4[31:16]};
		2'b11		:	shift_out5 = {shift_out4[15:0],shift_out4[31:16]};
		2'b00,2'b10 : 	shift_out5 = shift_out4;
		default 	: 	shift_out5 = shift_out4;
	endcase
end

assign data_out = shift_out5;
endmodule 
